﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

using Microsoft.Samples.Office.UnifiedCommunications.Gadget.EWSUtility;
using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Config;
using Microsoft.Samples.Office.UnifiedCommunications.Gadget.Events;

namespace Microsoft.Samples.Office.UnifiedCommunications.Gadget
{
    public partial class VoiceMail : Page
    {
        #region Variable Declarations
        private BackgroundWorker _worker;
        private List<VoicemailMessage> _voicemails;

        private bool _vmEnabled;
        private int _numUnreadVMs = 0;
        private string _message;

        private delegate void RaiseUnreadVoicemailEventDelegate(UnreadVoicemailEventArgs e);
        private Delegate raiseUnreadVoicemailEvent;

        private static VoiceMail _instance = null;

        private Point mouseDragStartPoint;
        private Point scrollStartOffset;
        #endregion

        public static VoiceMail Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new VoiceMail();
                    _instance.InitializeComponent();
                }
                return _instance;
            }
        }

        public VoiceMail()
        {
            _instance = this;

            InitializeComponent();

            raiseUnreadVoicemailEvent = new RaiseUnreadVoicemailEventDelegate(RaiseUnreadVoicemailEvent);

            GadgetEventManager.Instance.EWSUnauthorizedEvent += new EventHandler(Instance_EWSUnauthorizedEvent);

            this.Unloaded += new RoutedEventHandler(VoiceMail_Unloaded);
        }

        void VoiceMail_Unloaded(object sender, RoutedEventArgs e)
        {
            GadgetEventManager.Instance.EWSUnauthorizedEvent -= new EventHandler(Instance_EWSUnauthorizedEvent);
        }

        void RaiseUnreadVoicemailEvent(UnreadVoicemailEventArgs e)
        {
            GadgetEventManager.Instance.OnUnreadVoicemailEvent(e);
        }

        void RaiseVoicemailEnabledEvent(EventArgs e)
        {
            GadgetEventManager.Instance.OnVoicemailEnabledEvent(new EventArgs());
        } 

        void Instance_EWSUnauthorizedEvent(object sender, EventArgs e)
        {
            gridVMConfiguration.Visibility = Visibility.Visible;
            gridVoicemail.Visibility = Visibility.Collapsed;

            tbVMConfig.Text = String.Concat("An error occurred while attempting to access your voice mail.",
                Environment.NewLine, Environment.NewLine, 
                "Please verify your Exchange Web Services configuration information.");
        }

        void ProcessVoicemail()
        {
            // Verify that the gadget is configured
            //
            SettingsEWS curSettings = Gadget.CurrentSettings;
            if (!string.IsNullOrEmpty(curSettings.EWSUrl) || !string.IsNullOrEmpty(curSettings.ExchangeServer))
            {
                // Gadget is configured - Check if voicemail functinality has already been checked
                //
                EWSRequest ewsRequest = new EWSRequest(
                    curSettings.EWSUrl,
                    curSettings.DomainUser.Split(new char[] { '\\' })[1],
                    curSettings.Password,
                    curSettings.DomainUser.Split(new char[] { '\\' })[0]);

                if (curSettings.VoicemailEnabled.HasValue)
                {
                    if (curSettings.VoicemailEnabled == true)
                    {
                        gridVMConfiguration.Visibility = Visibility.Collapsed;
                        gridVoicemail.Visibility = Visibility.Visible;

                        _vmEnabled = true;
                        FetchVoicemail(ewsRequest);
                    }
                    else
                    {
                        gridVMConfiguration.Visibility = Visibility.Visible;
                        gridVoicemail.Visibility = Visibility.Collapsed;

                        _vmEnabled = false;
                        _message = "Sorry, voice mail doesn't currently appear to be configured in your organization.";
                    }
                }
                else
                {
                    // Check if voicemail is enabled
                    CheckIfVoicemailEnabled(ewsRequest);
                }
            }
            else
            {
                gridVMConfiguration.Visibility = Visibility.Visible;
                _message = "You must configure the gadget to connect to Exchange Web Services before retrieving voice mail.";
            }

            tbVMConfig.Text = _message;
        }

        void CheckIfVoicemailEnabled(EWSRequest ewsRequest)
        {
            _worker = new BackgroundWorker();
            _worker.WorkerReportsProgress = false;
            _worker.WorkerSupportsCancellation = false;

            _worker.DoWork += delegate(object s, DoWorkEventArgs args)
                {
                    EWSVoicemail.IsEnabledDelegate delegateVoicemailIsEnabled =
                        new EWSVoicemail.IsEnabledDelegate(EWSVoicemail.IsEnabled);
                    _vmEnabled = Convert.ToBoolean(this.Dispatcher.Invoke(
                        DispatcherPriority.Background, delegateVoicemailIsEnabled, ewsRequest));
                };

            _worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
                {
                    gridLoading.Visibility = Visibility.Collapsed;

                    SettingsEWS settings = Gadget.CurrentSettings;
                    settings.VoicemailEnabled = true;
                    Gadget.CurrentSettings = settings;

                    if (_vmEnabled)
                        RaiseVoicemailEnabledEvent(new EventArgs());

                    ProcessVoicemail();
                };

            _worker.RunWorkerAsync();

            tbVoicemailCount.Text = "Loading voice mail ...";

            gridVMConfiguration.Visibility = Visibility.Collapsed;
            tbVMConfig.Text = string.Empty;

            gridLoading.Visibility = Visibility.Visible;
        }

        void GetNumberUnreadVoicemails(EWSRequest ewsRequest)
        {
            _worker = new BackgroundWorker();
            _worker.WorkerReportsProgress = false;
            _worker.WorkerSupportsCancellation = false;

            _worker.DoWork += delegate(object s, DoWorkEventArgs args)
            {
                EWSVoicemail.GetNumberUnreadVoicemailsDelegate delegateGetNumberUnreadVoicemails =
                    new EWSVoicemail.GetNumberUnreadVoicemailsDelegate(EWSVoicemail.GetNumberUnreadVoicemails);
                _numUnreadVMs = Convert.ToInt32(this.Dispatcher.Invoke(
                    DispatcherPriority.Background, delegateGetNumberUnreadVoicemails, ewsRequest));
            };

            _worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
            {
                UnreadVoicemailEventArgs e = new UnreadVoicemailEventArgs(_numUnreadVMs);
                this.Dispatcher.Invoke(DispatcherPriority.Send, raiseUnreadVoicemailEvent, e);
            };

            _worker.RunWorkerAsync();
        }

        void FetchVoicemail(EWSRequest ewsRequest)
        {
            _worker = new BackgroundWorker();
            _worker.WorkerReportsProgress = false;
            _worker.WorkerSupportsCancellation = false;

            _worker.DoWork += delegate(object s, DoWorkEventArgs args)
                {
                    EWSVoicemail.GetVoicemailsDelegate delegateGetVoicemails =
                        new EWSVoicemail.GetVoicemailsDelegate(EWSVoicemail.GetVoicemails);
                    _voicemails = (List<VoicemailMessage>)(this.Dispatcher.Invoke(
                        DispatcherPriority.Background, delegateGetVoicemails, ewsRequest));
                };

            _worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
                {
                    gridLoading.Visibility = Visibility.Collapsed;

                    if (_voicemails != null)
                    {
                        if (_voicemails.Count > 0)
                            _message = String.Format("You have {0} voice mail message(s)", _voicemails.Count);
                        else
                            _message = "You have no voice mails.";

                        GetNumberUnreadVoicemails(ewsRequest);
                        DisplayVoicemail();

                        tbVoicemailCount.Text = _message;
                    }
                    else
                    {
                        Instance_EWSUnauthorizedEvent(this, new EventArgs());
                    }
                };

            _worker.RunWorkerAsync();
            tbVoicemailCount.Text = "Loading voice mail ...";

            gridLoading.Visibility = Visibility.Visible;
        }

        void DisplayVoicemail()
        {
            listBoxVM.ItemsSource = _voicemails;
        }

        void BackDoubleAnimation_Completed(object sender, EventArgs e) 
        {
            ProcessVoicemail();
        }

        private void listBoxVM_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            string owaUrl = Gadget.CurrentSettings.EWSUrl.ToLower().Replace("ews/exchange.asmx", "owa/");
            if (!String.IsNullOrEmpty(owaUrl))
            {
                VoicemailMessage vm = (VoicemailMessage)listBoxVM.SelectedItem;

                if (!String.IsNullOrEmpty(vm.itemId))
                {
                    string vmOwaUrl = String.Concat(owaUrl, "?ae=Item&a=Open&t=",
                        "IPM.Note.Microsoft.Voicemail.UM.CA", "&id=", vm.itemId.Replace("/", "%2f"));

                    try
                    {
                        Process processIE = new Process();
                        processIE.StartInfo.FileName = "iexplore.exe";
                        processIE.StartInfo.Arguments = vmOwaUrl;
                        processIE.Start();
                    }
                    catch
                    {
                        return;
                    }
                }
            }
        }

        /*
        protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
        {
            mouseDragStartPoint = e.GetPosition(this);
            scrollStartOffset.X = myScrollViewer.HorizontalOffset;
            scrollStartOffset.Y = myScrollViewer.VerticalOffset;

            // Update the cursor if scrolling is possible 
            this.Cursor = (myScrollViewer.ExtentWidth > myScrollViewer.ViewportWidth) ||
                (myScrollViewer.ExtentHeight > myScrollViewer.ViewportHeight) ?
                Cursors.ScrollAll : Cursors.Arrow;

            this.CaptureMouse();
            base.OnPreviewMouseDown(e);
        }

        protected override void OnPreviewMouseMove(MouseEventArgs e)
        {
            if (this.IsMouseCaptured)
            {
                // Get the new mouse position. 
                Point mouseDragCurrentPoint = e.GetPosition(this);

                // Determine the new amount to scroll. 
                Point delta = new Point(
                    (mouseDragCurrentPoint.X > this.mouseDragStartPoint.X) ? -(mouseDragCurrentPoint.X - this.mouseDragStartPoint.X) : (this.mouseDragStartPoint.X - mouseDragCurrentPoint.X),
                    (mouseDragCurrentPoint.Y > this.mouseDragStartPoint.Y) ? -(mouseDragCurrentPoint.Y - this.mouseDragStartPoint.Y) : (this.mouseDragStartPoint.Y - mouseDragCurrentPoint.Y));

                // Scroll to the new position. 
                myScrollViewer.ScrollToHorizontalOffset(this.scrollStartOffset.X + delta.X);
                myScrollViewer.ScrollToVerticalOffset(this.scrollStartOffset.Y + delta.Y);
            }
            base.OnPreviewMouseMove(e);
        }

        protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
        {
            if (this.IsMouseCaptured)
            {
                this.Cursor = Cursors.Arrow;
                this.ReleaseMouseCapture();
            }

            base.OnPreviewMouseUp(e);
        }
        */
    }
}